/**
 * 
 */
package wpmp.security.mgr.service;

import java.sql.Timestamp;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import wcommons.lang.DateUtils;
import wcommons.lang.NumberUtils;
import wcommons.lang.quickbean.Message;
import wpmp.security.mgr.base.BaseService;
import wpmp.security.mgr.dao.CodeDao;
import wpmp.security.mgr.dao.CodeSortDao;
import wpmp.security.mgr.entity.Code;

/**
 * @author Wayne.Wang<5waynewang@gmail.com>
 * @since 3:18:35 PM Mar 18, 2013
 */
@Component
@Transactional(rollbackFor = Exception.class)
public class CodeService extends BaseService {

	private static final Logger LOG = LoggerFactory.getLogger(CodeService.class);

	// 需要更新的字段
	private static final String[] UPDATE_PROPERTIES = { "name", "value", "memo" };

	@Autowired
	private CodeDao dao;
	@Autowired
	private CodeSortDao codeSortDao;

	public Code get(Long id) {
		Code entity = dao.get(id);
		if (entity == null) {
			return entity;
		}
		Code result = new Code();
		BeanUtils.copyProperties(entity, result);
		return result;
	}

	private Criteria getCriteria(Code entity) {
		Criteria criteria = dao.createCriteria(Restrictions.eq("sortId", entity.getSortId()));

		if (StringUtils.isNotBlank(entity.getText())) {
			criteria.add(Restrictions.like("text", entity.getText(), MatchMode.ANYWHERE));
		}
		return criteria;
	}

	public int count(Code entity) {
		return dao.queryForInt(getCriteria(entity));
	}

	public List<Code> list(Code entity) {
		return dao.queryForList(getCriteria(entity).addOrder(Order.asc("orderNum")));
	}

	/**
	 * 获取子类最大的排序号
	 * 
	 * @param id
	 * @return
	 */
	public int getMaxChildOrderNum(Long id) {
		Integer maxOrderNum = (Integer) dao.createCriteria(Restrictions.eq("sortId", id))
				.setProjection(Projections.max("orderNum")).uniqueResult();
		return maxOrderNum == null ? 0 : maxOrderNum.intValue();
	}

	public Message validateText(Code entity) {
		Criteria criteria = dao.createCriteria(Restrictions.eq("sortId", entity.getSortId()),
				Restrictions.eq("text", entity.getText()));
		if (NumberUtils.gtZero(entity.getId())) {
			criteria.add(Restrictions.ne("id", entity.getId()));
		}
		if (dao.queryForInt(criteria) > 0) {
			return Message.getErrorMessage("已存在名称[" + entity.getText() + "]");
		}
		return Message.getDefaultMessage();
	}

	public Message insert(Code entity) {
		Message message = validateText(entity);
		if (message.notpass()) {
			return message;
		}

		Timestamp currentTime = new Timestamp(System.currentTimeMillis());
		entity.setOrderNum(getMaxChildOrderNum(entity.getSortId()) + 1);
		entity.setCreateTime(currentTime);
		entity.setCreateUser(entity.getSysLoginName());
		entity.setUpdateTime(currentTime);
		entity.setUpdateUser(entity.getSysLoginName());
		dao.save(entity);

		return message;
	}

	public Message update(Code entity) {
		Message message = validateText(entity);
		if (message.notpass()) {
			return message;
		}

		Code result = dao.get(entity.getId());

		wcommons.beanutils.BeanUtils.copyProperties(result, entity, UPDATE_PROPERTIES, false);
		result.setUpdateTime(DateUtils.newTimestamp());
		result.setUpdateUser(entity.getSysLoginName());
		dao.save(result);

		return message;
	}

	public Message delete(Code entity) {
		if (ArrayUtils.isEmpty(entity.getIds())) {
			return Message.getErrorMessage("请选择您要删除的记录");
		}

		dao.delete(entity.getIds());

		Criteria criteria = dao.createCriteria(Restrictions.eq("sortId", entity.getSortId()));
		criteria.addOrder(Order.asc("orderNum"));
		List<Code> entities = dao.queryForList(criteria);
		if (CollectionUtils.isNotEmpty(entities)) {
			for (int i = 0; i < entities.size(); i++) {
				entities.get(i).setOrderNum(i + 1);
			}
			dao.save(entities);
		}

		return Message.getDefaultMessage();
	}

	public Message sort(Code entity) {
		Long[] ids = entity.getIds();
		Integer[] orderNums = new Integer[ids.length];
		for (int i = 0; i < ids.length; i++) {
			orderNums[i] = i + 1;
		}
		int[] status = dao.updateOrderNum(ids, orderNums);

		if (LOG.isDebugEnabled()) {
			LOG.debug("UPDATE Code's orderNum: ids[{}], return [{}]", ArrayUtils.toString(ids),
					ArrayUtils.toString(status));
		}

		return Message.getDefaultMessage();
	}
}
